package battlezone;

import java.awt.*;
import java.util.Collection;

import javax.swing.*;
import javax.vecmath.Color3f;

public class Canvas2D extends JPanel {

    private short _score;
    private short _lives;
    private short _ammo;
    private Tank _myTank;
    private Collection<BattlezoneObject> _objects;
    private static final Configuration _configuration = Configuration.getInstance();
    private static final int _ovalRadius = 65;
    private int _refresherPosX;
    private int _refresherSpeed;
    private int _refresherSignY;
    private boolean _isMoveRadarNeedleAllowed;

    public Canvas2D() {
        super();
        _score = 0;
        _lives = 0;
        _ammo = 0;
        _objects = null;
        _myTank = null;

        _refresherPosX = 0;
        _refresherSpeed = 2;
        _refresherSignY = 1;
        _isMoveRadarNeedleAllowed = false;

    }

    public void paint(Graphics g) {
        //Graphics2D g2 = (Graphics2D) g; 

        //Paint background in black
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());

        //Draw radar
        drawRadar(g);

        //Draw score, lives and ammo left
        drawStrings(g);
    }

    private void drawRadar(Graphics g) {
        int width, height;
        width = this.getWidth();
        height = this.getHeight();
        float detectabilityRange = _configuration.getDetectabilityRange();

        //Draw circle
        int centerX = (width / 2);
        int centerY = (height / 2);
        g.setColor(new Color(0, 255, 0));
        g.drawOval((width / 2) - (_ovalRadius), (height / 2) - (_ovalRadius), _ovalRadius * 2, _ovalRadius * 2);
        //Draw some useless stuff
        /* int sizeLine = 10;
        g.drawLine(centerX, centerY + _ovalRadius, centerX, centerY + _ovalRadius - sizeLine);
        g.drawLine(centerX, centerY - _ovalRadius, centerX, centerY - _ovalRadius + sizeLine);
        g.drawLine(centerX - _ovalRadius, centerY, centerX - _ovalRadius + sizeLine, centerY);
        g.drawLine(centerX + _ovalRadius, centerY, centerX + _ovalRadius - sizeLine, centerY); */

        if (_objects != null) {
            for (BattlezoneObject object : _objects) {
                //focus only on live tanks

                //compute distance between myTank and enemy tank
                double distBetweenObjects = Math.sqrt(Math.pow((double) object.getPositionX() - (double) _myTank.getPositionX(), 2) + Math.pow((double) object.getPositionY() - (double) _myTank.getPositionY(), 2));

                //Display only objects within the detectabilityRange
                if (distBetweenObjects < detectabilityRange) {

                    //find the new world position for the object
                    //when myTank position is set to (0,0)
                    float newWorldPosX = object.getPositionX() - _myTank.getPositionX();
                    float newWorldPosY = object.getPositionY() - _myTank.getPositionY();

                    //Convert object position into radar coordinate
                    int radarPosX = (int) ((newWorldPosX * _ovalRadius) / detectabilityRange);
                    int radarPosY = (int) ((newWorldPosY * _ovalRadius) / detectabilityRange);

                    //Rotate coordinate to set the radar always pointing the north
                    double myTankAzimuth = -_myTank.getAzimuthInRadians();
                    int newRadarPosX = (int) (Math.cos(myTankAzimuth) * radarPosX + Math.sin(myTankAzimuth) * radarPosY);
                    int newRadarPosY = (int) (-Math.sin(myTankAzimuth) * radarPosX + Math.cos(myTankAzimuth) * radarPosY);

                    //Define color: red for projectiles, green for tanks
                    if (object.getClass() == Projectile.class) {
                        g.setColor(new Color(255, 0, 0));
                    } else {
                        g.setColor(new Color(0, 255, 0));                    //Draw object
                    }
                    g.drawOval(centerX + newRadarPosX, centerY - newRadarPosY, 2, 2);
                }
            }
        }

        if (_isMoveRadarNeedleAllowed) {
            MoveRadarNeedle(g);
            _isMoveRadarNeedleAllowed = false;
        }


    }

    private void MoveRadarNeedle(Graphics g) {
        int centerX = (this.getWidth() / 2);
        int centerY = (this.getHeight() / 2);

        //Move needle
        _refresherPosX += _refresherSpeed;

        double refresherPosY = -Math.sqrt(Math.pow((double) _ovalRadius, 2) - Math.pow(_refresherPosX, 2));

        //Modify speed and sign for x and y values
        refresherPosY *= _refresherSignY;
        if (_refresherPosX > _ovalRadius) {
            _refresherSpeed = -_refresherSpeed;
            _refresherSignY = -_refresherSignY;
        }
        if (_refresherPosX < -_ovalRadius) {
            _refresherSpeed = -_refresherSpeed;
            _refresherSignY = -_refresherSignY;
        }

        //Draw needle
        g.setColor(new Color(0, 255, 0));
        g.drawLine(centerX, centerY, centerX + _refresherPosX, centerY + (int) refresherPosY);
    }

    public void moveRadarNeedle() {
        _isMoveRadarNeedleAllowed = true;
    }

    private void drawStrings(Graphics g) {
        int width, height;
        width = this.getWidth();
        height = this.getHeight();

        Font font = new Font("Courier", Font.BOLD, 20);
        g.setFont(font);
        g.setColor(new Color(0, 255, 0));

        int wText = (int) (width - (width / 4.0));
        int hText = (int) (height / 4.0);
        g.drawString("Score: " + _score, wText, hText);
        g.drawString("Lives: " + _lives, wText, hText * 2);
        g.drawString("Ammo: " + _ammo, wText, hText * 3);
    }

    public void setScore(short score) {
        _score = score;
    }

    public void setLives(short lives) {
        _lives = lives;
    }

    public void setAmmo(short ammo) {
        _ammo = ammo;
    }

    public void setObjects(Collection<BattlezoneObject> objects) {
        _objects = objects;
    }

    public void setMyTank(Tank myTank) {
        _myTank = myTank;
    }
}
